<!DOCTYPE html>

<html>

<head>
  <title>Example 06 - attribute</title>
  <script type="text/javascript" src="../three/build/three.js"></script>
  <script type="text/javascript" src="../three/examples/js/controls/OrbitControls.js"></script>
  <script type="text/javascript" src="../three/examples/js/libs/stats.min.js"></script>
  <style>
    body {
      margin: 0;
      overflow: hidden;
    }
  </style>
</head>

<body>

  <div id="Stats-output"></div>
  <div id="WebGL-output"></div>

  <script type="text/javascript">
    let stats, controls;
    let camera, scene, renderer;
    let boxMaterialShader = {
      vertexShader: `
      attribute vec3 aPosition;
      attribute vec4 aColor;
      varying vec4 vColor;
      void main(){
        vColor = aColor;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(aPosition, 1.0);
      }
    `,
      fragmentShader: `
      varying vec4 vColor;
      void main(){
        gl_FragColor = vColor;
      }
    `
    };

    //创建ShaderMaterial材质
    let material = new THREE.ShaderMaterial({
      vertexShader: boxMaterialShader.vertexShader,
      fragmentShader: boxMaterialShader.fragmentShader,
      side: THREE.DoubleSide
    });
    material.needsUpdate = true;

    function initScene() {
      scene = new THREE.Scene();
    }

    function initCamera() {
      camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
      camera.position.set(3, 4, 5);
      camera.lookAt(new THREE.Vector3(0, 0, 0));
    }

    function initLight() {
      //添加环境光
      const ambientLight = new THREE.AmbientLight(0xffffff);
      scene.add(ambientLight);

      const spotLight = new THREE.SpotLight(0xffffff);
      spotLight.position.set(5, 10, 20);
      spotLight.castShadow = true;
      scene.add(spotLight);
    }


    function initModel() {

      //创建BufferGeometry几何体
      const bufferGeom = new THREE.BufferGeometry();

      //设置顶点信息
      const v0 = [1.0, 1.0, 1.0];
      const v1 = [-1.0, 1.0, 1.0];
      const v2 = [-1.0, -1.0, 1.0];
      const v3 = [1.0, -1.0, 1.0];
      const v4 = [1.0, -1.0, -1.0];
      const v5 = [1.0, 1.0, -1.0];
      const v6 = [-1.0, 1.0, -1.0];
      const v7 = [-1.0, -1.0, -1.0];
      const positions = new Float32Array([
        ...v0, ...v1, ...v2, ...v3, // 前 index 0-3
        ...v0, ...v3, ...v4, ...v5, // 右 index 4-7
        ...v0, ...v5, ...v6, ...v1, // 上 index 8-11
        ...v1, ...v6, ...v7, ...v2, // 左 index 12-15
        ...v7, ...v4, ...v3, ...v2, // 下 index 16-19
        ...v4, ...v7, ...v6, ...v5, // 后 index 20-23 
      ]);
      bufferGeom.setAttribute('aPosition', new THREE.BufferAttribute(positions, 3));


      //设置顶点颜色信息
      const fontColor = [1.0, 0.0, 0.0, 0.9];
      const backColor = [1.0, 0.4, 0.9, 0.2];
      const leftColor = [0.0, 1.0, 0.0, 0.1];
      const rightColor = [0.0, 0.3, 0.6, 0.8];
      const topColor = [0.0, 0.8, 1.0, 0.4];
      const downColor = [0.7, 0.0, 0.2, 0.6];
      const colors = new Float32Array([
        ...fontColor, ...fontColor, ...fontColor, ...fontColor, // 前 index 0-3
        ...rightColor, ...rightColor, ...rightColor, ...rightColor, // 右 index 4-7
        ...topColor, ...topColor, ...topColor, ...topColor, // 上 index 8-11
        ...leftColor, ...leftColor, ...leftColor, ...leftColor, // 左 index 12-15
        ...downColor, ...downColor, ...downColor, ...downColor, // 下 index 16-19
        ...backColor, ...backColor, ...backColor, ...backColor, // 后 index 20-23 

      ]);

      bufferGeom.setAttribute('aColor', new THREE.BufferAttribute(colors, 4));

      //设置索引信息
      const indexs = new Uint16Array([
        0, 1, 2, 0, 2, 3, // 前
        4, 5, 6, 4, 6, 7, // 右
        8, 9, 10, 8, 10, 11, // 上
        12, 13, 14, 12, 14, 15, // 左
        16, 17, 18, 16, 18, 19, // 下
        20, 21, 22, 20, 22, 23 // 后

      ]);
      bufferGeom.index = new THREE.BufferAttribute(indexs, 1);

      //创建Mesh对象并添加到场景
      const mesh = new THREE.Mesh(bufferGeom, material);
      scene.add(mesh);
    }

    function initRender() {

      renderer = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true
      });
      //renderer.shadowMap.enabled = true // 显示阴影
      renderer.setPixelRatio(window.devicePixelRatio);
      renderer.setSize(window.innerWidth, window.innerHeight);
      renderer.setClearColor(0x0f2d48, 1); // 设置背景颜色
      renderer.toneMapping = THREE.ACESFilmicToneMapping;
      document.getElementById("WebGL-output").appendChild(renderer.domElement);
    }

    //初始化轨道控制器
    function initControls() {
      clock = new THREE.Clock(); // 创建THREE.Clock对象，用于计算上次调用经过的时间
      controls = new THREE.OrbitControls(camera, renderer.domElement);
      //controls.autoRotate = true; // 是否自动旋转
    }



    function init() {
      initScene();
      initCamera();
      initLight();
      initRender();
      initStats();
      initControls();
      initModel();
      render();
    }



    function updateFun() {
      stats.update();
      const delta = clock.getDelta(); // 获取自上次调用的时间差
      controls.update(delta); // 相机更新

    }

    function render() {
      updateFun();
      requestAnimationFrame(render);
      renderer.render(scene, camera);
    }

    function initStats() {
      stats = new Stats();
      stats.setMode(0); // 0: fps, 1: ms

      document.getElementById("Stats-output").appendChild(stats.domElement);
    }

    window.onload = init;
  </script>
</body>

</html>